package Middleware

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"time"

	"github.com/go-redis/redis/v8"
	"github.com/patrickmn/go-cache"
	"gopkg.in/ini.v1"
)

var (
	Cacher      *cache.Cache
	RedisClient *redis.Client
	UseRedis    bool // 是否使用 Redis
	LocalExpire time.Duration
	RedisExpire time.Duration
)

// InitCache 初始化缓存
func InitCache() {
	// 从配置文件中加载配置
	cfg, err := ini.Load("./Config/config.ini")
	if err != nil {
		panic(fmt.Sprintf("Failed to load config file: %v", err))
	}

	// 初始化 go-cache
	LocalExpire = time.Duration(cfg.Section("cache").Key("local_expire").MustInt(5)) * time.Minute
	Cacher = cache.New(LocalExpire, 10*time.Minute)

	// 初始化 Redis 客户端
	UseRedis = cfg.Section("redis").Key("enabled").MustBool(false)
	if UseRedis {
		RedisExpire = time.Duration(cfg.Section("cache").Key("redis_expire").MustInt(10)) * time.Minute
		RedisClient = redis.NewClient(&redis.Options{
			Addr:     cfg.Section("redis").Key("host").String() + ":" + cfg.Section("redis").Key("port").String(),
			Password: cfg.Section("redis").Key("password").String(),
			DB:       cfg.Section("redis").Key("db").MustInt(0),
		})

		// 测试 Redis 连接
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		if _, err := RedisClient.Ping(ctx).Result(); err != nil {
			panic(fmt.Sprintf("Failed to connect to Redis: %v", err))
		}
	}
}

// buildCacheKey 构建带路径的缓存键
func buildCacheKey(path, key string) string {
	return fmt.Sprintf("%s:%s", path, key)
}

// SetCache 设置缓存
func SetCache(path, key string, value interface{}, expiration time.Duration) {
	// 构建带路径的缓存键
	fullKey := buildCacheKey(path, key)

	// 设置本地缓存
	//Cacher.Set(fullKey, value, expiration)

	// 如果启用 Redis，设置 Redis 缓存
	if UseRedis {

		ctx := context.Background()
		jsonValue, err := json.Marshal(value)
		if err != nil {
			fmt.Printf("Failed to marshal value for Redis: %v\n", err)
			return
		}
		if err := RedisClient.Set(ctx, fullKey, jsonValue, expiration).Err(); err != nil {
			fmt.Printf("Failed to set Redis cache: %v\n", err)
		}
	}
}

// GetCache 获取缓存
func GetCache(path, key string, value interface{}) bool {
	// 构建带路径的缓存键
	fullKey := buildCacheKey(path, key)
	log.Printf("GetCache key: %s", fullKey)
	//// 先从本地缓存获取
	//if cachedValue, found := Cacher.Get(fullKey); found {
	//	value = cachedValue
	//	log.Printf("GetCache value: %v", value)
	//	return true
	//}

	// 如果启用 Redis，从 Redis 获取
	if UseRedis {
		ctx := context.Background()
		jsonValue, err := RedisClient.Get(ctx, fullKey).Result()
		if errors.Is(err, redis.Nil) {
			return false // 缓存不存在
		} else if err != nil {
			fmt.Printf("Failed to get Redis cache: %v\n", err)
			return false
		}

		// 反序列化 Redis 中的 JSON 数据
		if err := json.Unmarshal([]byte(jsonValue), value); err != nil {
			fmt.Printf("Failed to unmarshal Redis value: %v\n", err)
			return false
		}

		// 将 Redis 中的数据存入本地缓存
		Cacher.Set(fullKey, value, LocalExpire)
		return true
	}

	return false
}

// DeleteCache 删除缓存
func DeleteCache(path, key string) {
	// 构建带路径的缓存键
	fullKey := buildCacheKey(path, key)

	// 删除本地缓存
	Cacher.Delete(fullKey)

	// 如果启用 Redis，删除 Redis 缓存
	if UseRedis {
		ctx := context.Background()
		if err := RedisClient.Del(ctx, fullKey).Err(); err != nil {
			fmt.Printf("Failed to delete Redis cache: %v\n", err)
		}
	}
}
